package com.gk.panda.apis.service.impl;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gk.panda.apis.Vo.exports.ExportEventTodoVO;
import com.gk.panda.apis.dto.EventToDoListSearchDto;
import com.gk.panda.apis.entity.eventtodo.dto.*;
import com.gk.panda.apis.entity.eventtodo.vo.*;
import com.gk.panda.apis.enums.EventFlowRecordStatusEnum;
import com.gk.panda.apis.enums.EventToDoStatusEnum;
import com.gk.panda.apis.mapper.EventTodoMapper;
import com.gk.panda.apis.service.*;
import com.gk.panda.apis.util.ListCopyUtils;
import com.gk.panda.apis.util.excel.ExcelUtils;
import com.gk.panda.commons.constant.Constants;
import com.gk.panda.commons.exception.ServerException;
import com.gk.panda.commons.util.CodeUtils;
import com.gk.panda.commons.util.UserUtil;
import com.gk.panda.pojo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @ClassName: EventTodoServiceImpl
 * @Description: 待办事件
 * @author: Sir.yang
 * @date: 2022/11/3 14:46
 * @version: 1.0
 **/
@Service
@Slf4j
public class EventTodoServiceImpl extends ServiceImpl<EventTodoMapper, EventTodo> implements EventTodoService {

    private static final String FILE_SUFFIX = ".xlsx";

    @Autowired
    private EventResourcesService eventResourcesService;

    @Autowired
    private EventFlowRecordService eventFlowRecordService;

    @Autowired
    private OrgService orgService;

    @Autowired
    private RealtimeShootService realtimeShootService;


    /**
     * @description: 新增待办事件
     * @param: [dto]
     * @return: int (主键)
     * @date: 2022/11/4 11:11
     * @version: 1.0
     **/
    @Override
    public int saveEventTodoInfo(SaveEventTodoDto dto) {
        EventTodo eventTodo = new EventTodo();
        BeanUtils.copyProperties(dto, eventTodo);
        eventTodo.setReportTime(new Date());
        eventTodo.setCreateTime(new Date());
        //待办事件编号：SJ + 年 + 月+ 日+ 4自然数
        //获取当前时间最后一个编号
        String sn = baseMapper.selectSn(new Date());
        String abbr = UserUtil.getCurrentUserOrgAbbr();
        eventTodo.setEventSn(CodeUtils.getCode(sn, abbr+Constants.TODO_EVENT));
        baseMapper.insertSelective(eventTodo);
        return eventTodo.getId();
    }

    /**
     * @description: 获取待办事件列表上的数据统计
     * @param: []
     * @return: com.gk.panda.apis.entity.eventtodo.vo.EventToDoCountVo
     * @date: 2022/11/3 16:15
     * @version: 1.0
     **/
    @Override
    public EventToDoCountVo getEventToDoCount(EventToDoListSearchDto dto) {
        EventToDoCountVo vo = baseMapper.getEventToDoCount(dto);
        float v = Float.valueOf(vo.getEventCompletedNum()) / vo.getEventTotalNum();
        vo.setEventCompletionRate(v);
        return vo;
    }

    /**
     * @description: 获取PC待办事件列表
     * @param: [dto]
     * @return: com.baomidou.mybatisplus.extension.plugins.pagination.Page<com.gk.panda.apis.entity.eventtodo.vo.EventToDoListVo>
     * @date: 2022/11/3 16:15
     * @version: 1.0
     **/
    @Override
    public Page<EventToDoListVo> getEventToDoList(EventToDoListDto dto) {
        //分页查询
        Page<EventTodo> page = new Page<>(dto.getPageNumber(),dto.getPageSize());
        QueryWrapper<EventTodo> wrapper = new QueryWrapper<>();
        if(null != dto.getOrgId()){
//            List<Integer> orgIds = new ArrayList<>();
//            dto.getOrgId().forEach(orgId -> {
//                orgIds.addAll(orgService.getPuisneOrgIds(orgId));
//            });
//            List<Integer> list = orgIds.stream().distinct().collect(Collectors.toList());
//            wrapper.in("org_id", list);
            wrapper.in("org_id", dto.getOrgId());
        }
        if(null != dto.getEventStatus()){
            wrapper.in("event_status", dto.getEventStatus());
        }
        if(dto.getReportStartDate() !=null && dto.getReportEndDate() != null){
            wrapper.between("report_time", dto.getReportStartDate(), dto.getReportEndDate());
        }
        if(dto.getFinishStartDate() !=null && dto.getFinishEndDate() != null){
            wrapper.between("finish_time", dto.getFinishStartDate(), dto.getFinishEndDate());
        }
        if(StringUtils.isNotEmpty(dto.getSearchParam())){
            wrapper.and(queryWrapper -> {
                queryWrapper.like("event_sn", dto.getSearchParam())
                        .or().like("event_title", dto.getSearchParam())
                        .or().like("fk_update",dto.getSearchParam())
                        .or().like("event_description",dto.getSearchParam());
            });
        }
        wrapper.eq("del_flag", Constants.ZERO);
        Page<EventTodo> eventTodoPage = baseMapper.selectPage(page, wrapper);
        //转换返回数据
        Page<EventToDoListVo> voPage = new Page<>();
        if(!CollectionUtils.isEmpty(eventTodoPage.getRecords())){
            List<EventToDoListVo> vos = eventTodoPage.getRecords().stream().map(event -> {
                EventToDoListVo vo = new EventToDoListVo();
                BeanUtils.copyProperties(event, vo);
                vo.setEventStatus(EventToDoStatusEnum.getDescByCode(event.getEventStatus()));
                return vo;
            }).collect(Collectors.toList());
            voPage.setRecords(vos);
            voPage.setPages(eventTodoPage.getPages());
            voPage.setCurrent(eventTodoPage.getCurrent());
            voPage.setSize(eventTodoPage.getSize());
            voPage.setTotal(eventTodoPage.getTotal());
        }
        return voPage;
    }

    /**
     * @description: 获取PC待办事件详情数据
     * @param: [eventId]
     * @return: com.gk.panda.apis.entity.eventtodo.vo.EventToDoDetailsVo
     * @date: 2022/11/3 16:15
     * @version: 1.0
     **/
    @Override
    public EventToDoDetailsVo getEventToDoDetails(Integer eventId) {
        EventToDoDetailsVo vo = new EventToDoDetailsVo();
        //获取事件数据
        EventTodo eventTodo = baseMapper.selectByPrimaryKey(eventId);
        BeanUtils.copyProperties(eventTodo, vo);
        //获取图片视频信息
        List<EventResources> resourcesList = eventResourcesService.getEventResourcesListByEventId(eventId);
        if(!CollectionUtils.isEmpty(resourcesList)){
            List<EventResourcesVo> voList = resourcesList.stream().map(resources -> {
                EventResourcesVo resourcesVo = new EventResourcesVo();
                resourcesVo.setFileType(resources.getFileType());
                resourcesVo.setFileUrl(resources.getFileUrl());
                return resourcesVo;
            }).collect(Collectors.toList());
            vo.setResourceAddress(voList);
        }
        //获取流转记录信息
        List<EventFlowRecord> records = eventFlowRecordService.getEventFlowRecordListByEventId(eventId);
        if(!CollectionUtils.isEmpty(records)){
            List<EventFlowRecordVo> voList = records.stream().map(record -> {
                EventFlowRecordVo recordVo = new EventFlowRecordVo();
                BeanUtils.copyProperties(record, recordVo);
                return recordVo;
            }).collect(Collectors.toList());
            vo.setCirculationRecord(voList);
        }
        return vo;
    }

    /**
     * @description: PC完成待办事件
     * @param: [eventId]
     * @return: boolean
     * @date: 2023年1月5日16:51:31
     * @version: 1.0
     **/
    @Override
    @Transactional
    public boolean finishEventTodo(Integer eventId) {
        try {
            EventTodo eventTodo = getById(eventId);
            eventTodo.setFinishTime(new Date());
            eventTodo.setFkUpdate(UserUtil.getCurrentUser());
            eventTodo.setUpdateName(UserUtil.getCurrentUserName());
            eventTodo.setUpdateTime(new Date());
            eventTodo.setEventStatus(EventToDoStatusEnum.PROCESSING_COMPLETED.getCode());
            boolean update = updateById(eventTodo);
            if (!update) return false;
            //保存流转记录
            AcceptanceEventDto eventDto = new AcceptanceEventDto();
            eventDto.setEventId(eventId);
            eventDto.setFkRecipient(UserUtil.getCurrentUser());
            eventDto.setRecipientName(UserUtil.getCurrentUserName());
            eventFlowRecordService.saveRecordByStatus(eventDto, EventFlowRecordStatusEnum.PROCESSING_COMPLETED.getCode(), Constants.COMPLETED);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * @description: PC删除待办事件
     * @param: [eventId]
     * @return: boolean
     * @date: 2023年1月5日17:19:11
     * @version: 1.0
     **/
    @Override
    @Transactional
    public boolean deleteEventTodo(Integer eventId) {
        boolean remove = removeById(eventId);
        if (!remove) return false;
        //删除流转记录
        eventFlowRecordService.remove(Wrappers.<EventFlowRecord>lambdaQuery().eq(EventFlowRecord::getEventId,eventId));
        //删除事件图片视频资源
        eventResourcesService.remove(Wrappers.<EventResources>lambdaQuery().eq(EventResources::getEventId,eventId));
        //关联实时抓拍图片视频归档状态回滚
        List<RealtimeShoot> realtimeShoots = realtimeShootService.list(Wrappers.<RealtimeShoot>lambdaQuery().eq(RealtimeShoot::getFileRelation, eventId));
        if (!CollectionUtils.isEmpty(realtimeShoots)) {
            realtimeShoots.forEach(realtimeShoot -> realtimeShootService.update(Wrappers.<RealtimeShoot>lambdaUpdate().eq(RealtimeShoot::getId,realtimeShoot.getId())
                    .set(RealtimeShoot::getFileStatus,0).set(RealtimeShoot::getFileRelation,null).set(RealtimeShoot::getFileType,null)));
        }
        return true;
    }

    /**
     * @description: TODO 待办事件批量导出数据查询
     * @param: [dto]
     * @return: java.util.List<com.gk.panda.apis.entity.eventtodo.vo.EventToDoListVo>
     * @date: 2022/11/3 16:15
     * @version: 1.0
     **/
    @Override
    public List<EventToDoListVo> getBatchExportData(EventToDoListDto dto) {
        return null;
    }

    @Override
    public int saveBatteryEvent(DeviceManager device) throws UnsupportedEncodingException {
        //先看是否已生成该设备的低电量事件并且未完成
        EventTodo eventTodo = getOne(Wrappers.<EventTodo>lambdaQuery().eq(EventTodo::getDeviceSn, device.getDeviceSn())
                .ne(EventTodo::getEventStatus, 2));
        if (eventTodo == null) {
            SaveEventTodoDto savedto = new SaveEventTodoDto();
            savedto.setLatitude(device.getLatitude());
            savedto.setLongitude(device.getLongitude());
            savedto.setFkCreate(UserUtil.getCurrentUser());
            savedto.setCreateName(UserUtil.getCurrentUserName());
            savedto.setEventTitle("红外摄像机电量不足");
            savedto.setOrgId(device.getFkOrgId());
            savedto.setOrgName(device.getOrgName());
            savedto.setDeviceSn(device.getDeviceSn());
            savedto.setDeploymentPosition(device.getDeviceAddress());
            return saveEventTodoInfo(savedto);
        }
        return 0;
    }


    /**
     * ----------------------------APP------------------------
     **/

    /**
     * @description: App待办事件列表数据统计
     * @param: [dto]
     * @return: java.lang.Integer
     * @date: 2022/11/4 10:57
     * @version: 1.0
     **/
    @Override
    public Long getEventToDoListCountForApp(EventTodoAppListDto dto) {
        if(null == dto.getOrgId()){
            throw new ServerException("机构ID不能为空！");
        }
        // 获取当前机构下所有机构集合
        List<Integer> orgIds = orgService.getPuisneOrgIds(dto.getOrgId());
        QueryWrapper<EventTodo> wrapper = new QueryWrapper<>();
        wrapper.eq("event_status", EventToDoStatusEnum.TO_BE_VIEWED.getCode());
        wrapper.eq("del_flag", Constants.ZERO);
        wrapper.in(!CollectionUtils.isEmpty(orgIds),"org_id", orgIds);
        return baseMapper.selectCount(wrapper);
    }

    /**
     * @description: App待办事件列表数据获取
     * @param: [orgId]
     * @return: java.util.List<com.gk.panda.apis.entity.eventtodo.vo.EventToDoListByAppVo>
     * @date: 2022/11/3 22:45
     * @version: 1.0
     **/
    @Override
    public Page<EventToDoListByAppVo> getEventToDoListForApp(EventTodoAppListDto dto) {
        if(null == dto.getOrgId()){
            throw new ServerException("机构ID不能为空！");
        }
        // 获取当前机构下所有机构集合
        List<Integer> orgIds = orgService.getPuisneOrgIds(dto.getOrgId());
        //分页查询
        Page<EventTodo> page = new Page<>(dto.getPageNumber(),dto.getPageSize());
        QueryWrapper<EventTodo> wrapper = new QueryWrapper<>();
        wrapper.in(!CollectionUtils.isEmpty(orgIds),"org_id", orgIds);
        wrapper.eq("del_flag", Constants.ZERO);
        Page<EventTodo> eventTodoPage = baseMapper.selectPage(page, wrapper);
        //转换返回数据
        Page<EventToDoListByAppVo> voPage = new Page<>();
        if(!CollectionUtils.isEmpty(eventTodoPage.getRecords())){
            List<EventToDoListByAppVo> vos = eventTodoPage.getRecords().stream().map(event -> {
                EventToDoListByAppVo vo = new EventToDoListByAppVo();
                BeanUtils.copyProperties(event, vo);
                vo.setEventStatus(EventToDoStatusEnum.getDescByCode(event.getEventStatus()));
                return vo;
            }).collect(Collectors.toList());
            voPage.setRecords(vos);
            voPage.setPages(eventTodoPage.getPages());
            voPage.setCurrent(eventTodoPage.getCurrent());
            voPage.setSize(eventTodoPage.getSize());
            voPage.setTotal(eventTodoPage.getTotal());
        }
        return voPage;
    }

    /**
     * @description: 受理事件
     * @param: [eventId]
     * @return: Integer
     * @date: 2022/11/3 22:48
     * @version: 1.0
     **/
    @Override
    @Transactional
    public Integer acceptanceEvent(AcceptanceEventDto dto) {
        if(null == dto.getEventId()
                || StringUtils.isEmpty(dto.getFkRecipient())
                || StringUtils.isEmpty(dto.getRecipientName())){
            throw new ServerException("请传入参数！");
        }
        //事件受理是该事件在待查看状态下APP用户进行受理，状态更改为处理中，处理事件只能由受理人进行处理
        //受理事件需要添加受理记录和处理中记录，且更改事件状态为处理中
        eventFlowRecordService.saveRecordByStatus(dto, EventFlowRecordStatusEnum.ACCEPTANCE.getCode(), Constants.ACCEPTANCE);
        eventFlowRecordService.saveRecordByStatus(dto, EventFlowRecordStatusEnum.PROCESSING.getCode(), Constants.RECEIVEEVENT);
        //更新事件状态
        EventTodo eventTodo = new EventTodo();
        eventTodo.setId(dto.getEventId());
        eventTodo.setEventStatus(EventToDoStatusEnum.PROCESSING.getCode());
        eventTodo.setUpdateName(dto.getRecipientName());
        eventTodo.setUpdateTime(new Date());
        eventTodo.setFkUpdate(dto.getFkRecipient());
        return baseMapper.updateByPrimaryKeySelective(eventTodo);
    }

    /**
     * @description: 事件处理
     * @param: [dto]
     * @return: Integer
     * @date: 2022/11/3 23:36
     * @version: 1.0
     **/
    @Override
    @Transactional
    public Integer handelEvent(HandelEventDto dto) {
        if(null == dto.getEventId()
                || StringUtils.isEmpty(dto.getFkRecipient())
                || StringUtils.isEmpty(dto.getRecipientName())
                || CollectionUtils.isEmpty(dto.getResourceAddress())){
            throw new ServerException("请传入参数！");
        }
        //验证当前用户是否是该事件的受理人
        EventFlowRecord eventFlowRecord = eventFlowRecordService.getEventFlowRecordByEventIdAndStatus(dto.getEventId(), EventFlowRecordStatusEnum.ACCEPTANCE.getCode());
        if(ObjectUtils.isEmpty(eventFlowRecord)){
            throw new ServerException("该事件未受理不能进行处理！");
        }
        if(!eventFlowRecord.getFkRecipient().equals(dto.getFkRecipient())){
            throw new ServerException("该事件只能由受理人进行处理！");
        }
        //保存文件信息
        eventResourcesService.saveResourceByHandelEvent(dto);
        //保存流转记录
        AcceptanceEventDto eventDto = new AcceptanceEventDto();
        eventDto.setEventId(dto.getEventId());
        eventDto.setFkRecipient(dto.getFkRecipient());
        eventDto.setRecipientName(dto.getRecipientName());
        eventFlowRecordService.saveRecordByStatus(eventDto, EventFlowRecordStatusEnum.PROCESSING_COMPLETED.getCode(), Constants.COMPLETED);
        //保存事件信息及更新状态
        EventTodo eventTodo = new EventTodo();
        eventTodo.setId(dto.getEventId());
        if(StringUtils.isNotEmpty(dto.getTextDescription())){
            eventTodo.setTextDescription(dto.getTextDescription());
        }
        eventTodo.setEventStatus(EventToDoStatusEnum.PROCESSING_COMPLETED.getCode());
        eventTodo.setUpdateName(dto.getRecipientName());
        eventTodo.setUpdateTime(new Date());
        eventTodo.setFinishTime(new Date());
        eventTodo.setFkUpdate(dto.getFkRecipient());
        return baseMapper.updateByPrimaryKeySelective(eventTodo);
    }

    @Override
    public void exportEventTodo(HttpServletResponse response) {
        List<EventTodo> eventTodos = list();
        List<ExportEventTodoVO> vos = ListCopyUtils.copyListProperties(eventTodos, ExportEventTodoVO::new);
        // 导出
        ExportParams params = new ExportParams();
        params.setSheetName("待办事件");
        params.setHeight((short) 15);
        Workbook workbook = ExcelExportUtil.exportBigExcel(params, ExportEventTodoVO.class, vos);
        ExcelExportUtil.closeExportBigExcel();
        // 生成文件
        String downloadFileName = "待办事件导出" + FILE_SUFFIX;
        ExcelUtils.download(downloadFileName, workbook, response);
    }
}
